package biz.datalk.industrialland.admin.modules.system.service.impl;

import biz.datalk.industrialland.admin.component.shiro.CustomLoginUser;
import biz.datalk.industrialland.admin.modules.system.mapper.ISysConfigExtMapper;
import biz.datalk.industrialland.admin.modules.system.pojo.dto.SysConfigDTO;
import biz.datalk.industrialland.admin.modules.system.service.ISysConfigService;
import biz.datalk.industrialland.admin.modules.util.ShiroUtil;
import biz.datalk.industrialland.common.def.enums.DBYNEnum;
import biz.datalk.industrialland.common.exception.ServiceException;
import biz.datalk.industrialland.common.result.UnifyResult;
import biz.datalk.industrialland.common.result.UnifyResultUtil;
import biz.datalk.industrialland.common.util.EntityIdUtils;
import biz.datalk.industrialland.common.util.I18NUtil;
import biz.datalk.industrialland.common.util.RedisUtil;
import biz.datalk.industrialland.mbg.mapper.SysConfigMapper;
import biz.datalk.industrialland.mbg.pojo.po.SysConfig;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @author tarofang@163.com
 * @date 2019-12-27
 */
@Slf4j
@Service
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class SysConfigServiceImpl implements ISysConfigService {

    final private SysConfigMapper sysConfigMapper;
    final private ISysConfigExtMapper sysConfigExtMapper;
    private final RedisUtil redisUtil;

    @Autowired
    public SysConfigServiceImpl(SysConfigMapper sysConfigMapper, ISysConfigExtMapper sysConfigExtMapper, RedisUtil redisUtil) {
        this.sysConfigMapper = sysConfigMapper;
        this.sysConfigExtMapper = sysConfigExtMapper;
        this.redisUtil = redisUtil;
    }


    @Override
    public List<SysConfig> selectAllValid() {
        QueryWrapper<SysConfig> queryMapper = new QueryWrapper<>();
        queryMapper.eq(SysConfig.COL_IS_VALID, DBYNEnum.Y.name());
        List<SysConfig> sysConfigs = sysConfigMapper.selectList(queryMapper);

        // SysConfigExample example = new SysConfigExample();
        // SysConfigExample.Criteria criteria = example.createCriteria();
        // criteria.andIsValidEqualTo(DBYNEnum.Y.name());
        //
        // // criteria.andIsDeleteEqualTo(DBYNEnum.N.name()); 删除
        // List<SysConfig> sysConfigs = sysConfigMapper.selectByExample(example);

        return CollectionUtils.isNotEmpty(sysConfigs) ? sysConfigs : new ArrayList<>();
    }

    @Override
    public UnifyResult list(SysConfigDTO sysConfigDTO) {
        QueryWrapper<SysConfig> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc(SysConfig.COL_UPDATE_TIME);
        if (StringUtils.isNotBlank(sysConfigDTO.getCfgName())) {
            queryWrapper.like(SysConfig.COL_CFG_NAME, sysConfigDTO.getCfgName().trim());
        }
        if (StringUtils.isNotBlank(sysConfigDTO.getCfgKey())) {
            queryWrapper.like(SysConfig.COL_CFG_KEY, sysConfigDTO.getCfgKey().trim());
        }

        IPage<SysConfig> page = new Page<>(sysConfigDTO.getPageNumber(), sysConfigDTO.getPageSize());
        IPage<SysConfig> pageInfo = sysConfigMapper.selectPage(page, queryWrapper);

        return UnifyResult.success().mapData().put("rows", pageInfo.getRecords()).put("total", pageInfo.getTotal());
    }

    @Override
    public UnifyResult add(SysConfigDTO sysConfigDTO) {
        CustomLoginUser customLoginUser = ShiroUtil.currentLoginUser();
        UnifyResult result = checkSysconfig(sysConfigDTO, Boolean.FALSE);
        if (UnifyResultUtil.isFail(result)) {
            return result;
        }

        Date now = new Date();
        SysConfig sysConfig = new SysConfig();
        sysConfig.setCfgName(sysConfigDTO.getCfgName());
        sysConfig.setCfgKey(sysConfigDTO.getCfgKey().trim());
        sysConfig.setCfgValue(sysConfigDTO.getCfgValue());
        sysConfig.setCfgRemark(StringUtils.trimToEmpty(sysConfigDTO.getCfgRemark()));
        sysConfig.setCfgExpire(sysConfigDTO.getCfgExpire());
        sysConfig.setIsValid(DBYNEnum.Y.name());
        sysConfig.setIsDelete(DBYNEnum.N.name());
        sysConfig.setCreateBy(customLoginUser.getId());
        sysConfig.setCreateName(customLoginUser.getRealname());
        sysConfig.setCreateTime(now);
        sysConfig.setUpdateBy(customLoginUser.getId());
        sysConfig.setUpdateName(customLoginUser.getRealname());
        sysConfig.setUpdateTime(now);

        int resInt = sysConfigMapper.insertSelective(sysConfig);
        if (resInt != 1) {
            throw new ServiceException(I18NUtil.getMsg("message.sys.config.add.fail"));
        }

        redisUtil.set(sysConfig.getCfgKey(), sysConfig.getCfgValue(), sysConfig.getCfgExpire());
        log.debug("Add SysConfig key=[{}],value=[{}],expire=[{}]", sysConfig.getCfgKey().trim(), sysConfig.getCfgValue(), sysConfig.getCfgExpire());

        return UnifyResult.success();
    }

    private UnifyResult checkSysconfig(SysConfigDTO sysConfigDTO, Boolean isUpdate) {
        String cfgKey = StringUtils.trimToEmpty(sysConfigDTO.getCfgKey());
        SysConfig exists = selectByCfgKey(cfgKey);

        if (!isUpdate) {
            if (exists != null) {
                return UnifyResult.fail(I18NUtil.getMsg("message.sys.config.exists.sysKey", cfgKey));
            }
        } else {
            if (exists != null && !Objects.equals(sysConfigDTO.getId(), exists.getId())) {
                return UnifyResult.fail(I18NUtil.getMsg("message.sys.config.exists.sysKey", cfgKey));
            }
        }

        return UnifyResult.success();
    }

    @Override
    public UnifyResult edit(SysConfigDTO sysConfigDTO) {
        CustomLoginUser customLoginUser = ShiroUtil.currentLoginUser();
        UnifyResult result = checkSysconfig(sysConfigDTO, Boolean.TRUE);
        if (UnifyResultUtil.isFail(result)) {
            return result;
        }
        Date now = new Date();
        SysConfig upSysConfig = new SysConfig();
        upSysConfig.setId(sysConfigDTO.getId());
        upSysConfig.setCfgName(sysConfigDTO.getCfgName());
        upSysConfig.setCfgKey(sysConfigDTO.getCfgKey().trim());
        upSysConfig.setCfgValue(sysConfigDTO.getCfgValue());
        upSysConfig.setCfgRemark(StringUtils.trimToEmpty(sysConfigDTO.getCfgRemark()));
        upSysConfig.setCfgExpire(sysConfigDTO.getCfgExpire());
        upSysConfig.setUpdateBy(customLoginUser.getId());
        upSysConfig.setUpdateName(customLoginUser.getRealname());
        upSysConfig.setUpdateTime(now);
        String isDelete = sysConfigDTO.getIsDelete();
        if (StringUtils.isNotBlank(isDelete) && StringUtils.equalsAny(isDelete, DBYNEnum.Y.name(), DBYNEnum.N.name())) {
            upSysConfig.setIsDelete(isDelete);
        }
        String isValid = sysConfigDTO.getIsValid();
        if (StringUtils.isNotBlank(isValid) && StringUtils.equalsAny(isValid, DBYNEnum.Y.name(), DBYNEnum.N.name())) {
            upSysConfig.setIsValid(isValid);
        }
        int resInt = sysConfigMapper.updateByPrimaryKeySelective(upSysConfig);
        if (resInt != 1) {
            throw new ServiceException(I18NUtil.getMsg("message.sys.config.update.fail"));
        }

        redisUtil.set(upSysConfig.getCfgKey(), upSysConfig.getCfgValue(), upSysConfig.getCfgExpire());
        log.debug("Update SysConfig key=[{}],value=[{}],expire=[{}]", upSysConfig.getCfgKey().trim(), upSysConfig.getCfgValue(), upSysConfig.getCfgExpire());

        return UnifyResult.success();
    }

    @Override
    public UnifyResult delete(SysConfigDTO sysConfigDTO) {
        SysConfig exists = sysConfigMapper.selectById(sysConfigDTO.getId());
        if (exists == null) {
            return UnifyResult.fail(I18NUtil.getMsg("message.sys.config.no.exists.or.delete"));
        }
        int resInt = sysConfigMapper.deleteById(sysConfigDTO.getId());
        if (resInt != 1) {
            throw new ServiceException(I18NUtil.getMsg("message.sys.config.delete.fail"));
        }

        redisUtil.del(exists.getCfgKey());
        log.debug("Delete SysConfig key=[{}],value=[{}],expire=[{}]", exists.getCfgKey().trim(), exists.getCfgValue(), exists.getCfgExpire());

        return UnifyResult.success();
    }

    @Override
    public UnifyResult batchDelete(SysConfigDTO sysConfigDTO) {
        List<Long> sysids = EntityIdUtils.parseIds(sysConfigDTO.getSysids());

        QueryWrapper<SysConfig> queryWrapper = new QueryWrapper<>();
        queryWrapper.in(SysConfig.COL_ID, sysids);
        List<SysConfig> list = sysConfigMapper.selectList(queryWrapper);
        if (CollectionUtils.size(list) != sysids.size()) {
            throw new ServiceException(I18NUtil.getMsg("message.sys.config.delete.fail"));
        }

        int resInt = sysConfigMapper.deleteBatchIds(sysids);
        if (resInt != sysids.size()) {
            throw new ServiceException(I18NUtil.getMsg("message.sys.config.delete.fail"));
        }

        list.forEach(item -> {
            redisUtil.del(item.getCfgKey());
            log.debug("refreshCache key=[{}],value=[{}],expire=[{}]", item.getCfgKey().trim(), item.getCfgValue(), item.getCfgExpire());
        });

        return UnifyResult.success();
    }

    @Override
    public UnifyResult refresh() {
        List<SysConfig> list = this.selectAllValid();
        list.forEach(item -> {
            redisUtil.set(item.getCfgKey(), item.getCfgValue(), item.getCfgExpire());
            log.debug("refreshCache key=[{}],value=[{}],expire=[{}]", item.getCfgKey().trim(), item.getCfgValue(), item.getCfgExpire());
        });
        return UnifyResult.success();
    }

    @Override
    public SysConfig selectByCfgKey(String cfgKey) {
        if (StringUtils.isBlank(cfgKey)) {
            return null;
        }

        return sysConfigExtMapper.selectByCfgKey(cfgKey.trim());
    }
}
